/*
 * @Description:主入口
 * @Version: 2.0
 * @Autor: wiz
 * @Date: 2022-09-03 20:47:40
 * @LastEditors: swc
 * @LastEditTime: 2024-07-30 17:48:15
 */
/* eslint-disable no-new */
import lexicon from '@/lib/lexicon';
import { Tsrv } from '@/services';
import CKEditor from '@ckeditor/ckeditor5-vue2';
import axios from 'axios';
import Vue from 'vue';
import VueNativeSock from 'vue-native-websocket';

// import 'echarts';
import Viewer from 'v-viewer';
import ViewUI from 'view-design';

import 'view-design/dist/styles/iview.css';
import 'viewerjs/dist/viewer.css';

import VueCompositionAPI from '@vue/composition-api';
import VXETable from 'vxe-table';
import VXETablePluginIView from 'vxe-table-plugin-iview'; // vxe使用iview扩展
import 'vxe-table-plugin-iview/dist/style.css'; // vxe原样式
// import 'vxe-table/lib/style.css';
// scss导致图标乱码问题
import 'vxe-table/styles/index.scss';
import App from './App.vue'; // 入口
import './assets/css/global.scss';

import './assets/css/components/ui-lib/theme.less'; // iview覆盖样式
import './assets/css/components/ui-lib/vxe.scss'; // vxe覆盖样式

import './components/init';
import { i18n } from './config/i18n.config';
import './config/msg.config';
import { initTheme } from './config/theme.config';
import './config/vxetable.config'; // vxe默认配置
import { T_return } from './obj/class';
import router from './router/index'; // vue router
import './router/routerEvents'; // vue router events
import store from './store/index';

const wasmfuncNames = [
  'wGetKey',
  'wEnCode',
  'wDeCode',
  'wZipStr',
  'wUnZipStr',
  'wAesDecrypt',
  'wAesEncrypt',
  'wCalculateSHA256',
  'wQBEToSQLRegexp',
  'wQBEToSQLLike',
  'wSQLLikeToRegexp',
  'wSQLRegexpToLike',
  'wIsJsonObj'
];
Vue.use(CKEditor);

Vue.use(VueCompositionAPI);
Vue.use(ViewUI, {
  i18n: (key: string, value: string) => i18n.t(key, value)
});

VXETable.setConfig({
  i18n: (key, args) => i18n.t(key, args).toString()
});
Vue.use(VXETable);

VXETable.use(VXETablePluginIView);

// elementDetecter
const elementResizeDetectorMaker: any = require('element-resize-detector');

Vue.prototype.$elementDetecter = elementResizeDetectorMaker;

Vue.prototype.$utils = Tsrv.utils;
Vue.prototype.$bus = new Vue(); // 注册总线
Vue.prototype.$mbus = new Vue(); // 注册magicbox总线
Vue.prototype.$srv = Tsrv; // 注册全局服务方便调试
Tsrv.eventBus = Vue.prototype.$bus;
initTheme();

Vue.use(Viewer);

Vue.config.productionTip = false;

const injectScript = (src: string): Promise<void> => {
  return new Promise((resolve, reject) => {
    // 避免重复加载
    if (document.querySelector(`script[src="${src}"]`)) {
      resolve();
      return;
    }
    const script = document.createElement('script');
    script.src = src;
    script.async = true;
    script.onload = () => resolve();
    script.onerror = () => reject(new Error(`Failed to load script ${src}`));
    document.head.appendChild(script);
  });
};

const loadWasm = async (
  wasmPath = '/wasm/utils.wasm',
  execPath = '/wasm/wasm_exec.js'
): Promise<void> => {
  await injectScript(execPath);
  if (!(window as any).Go) {
    throw new Error('wasm_exec.js 加载失败: window.Go 未定义');
  }

  const go = new (window as any).Go();
  const resp = await fetch(wasmPath);
  if (!resp.ok) {
    throw new Error(`WASM 加载失败: ${resp.status} ${resp.statusText}`);
  }

  const result = await WebAssembly.instantiateStreaming(resp, go.importObject);
  go.run(result.instance);

  if (!globalThis.wasmMethods || typeof globalThis.wasmMethods !== 'object') {
    throw new Error('globalThis.wasmMethods 未定义或不是对象');
  }

  wasmfuncNames.forEach(methodName => {
    if (typeof globalThis.wasmMethods[methodName] !== 'function') {
      throw new Error(
        `WASM方法 ${methodName} 未在 globalThis.wasmMethods 中找到`
      );
    }

    if (window[methodName]) {
      console.warn(`window.${methodName} 已被占用，可能导致冲突`);
    }

    window[methodName] = (...args) => {
      try {
        const jsonResult = globalThis.wasmMethods[methodName](...args);
        const res = JSON.parse(jsonResult);
        return new T_return(res._err || '').setReturnData(
          'data',
          res.returnData.data
        );
      } catch (e) {
        throw new Error(`WASM方法 ${methodName} 执行失败: ${e.message}`);
      }
    };
  });
};

const getConf = async () => {
  const { data } = await axios.get(lexicon.url.getConfFilePath);
  Vue.prototype.$config = data;
  Vue.use(VueNativeSock, data.webSocketHost, {
    connectManually: true
  });
};
const newVue = () => {
  new Vue({
    el: '#app',
    router,
    store,
    i18n,
    components: {
      App
    },
    render: (h: any) => h(App)
  });
};

(async () => {
  await loadWasm();
  await getConf();
  newVue();
})();
